<script setup lang="ts">
import { useClipboard, useThrottleFn } from "@vueuse/core";
import { useGeneralDataStore, useSettingStore } from "@/store";
import hljs from "highlight.js/lib/core";
import javascript from "highlight.js/lib/languages/javascript";
import python from "highlight.js/lib/languages/python";
import bash from "highlight.js/lib/languages/bash";
import html from "highlight.js/lib/languages/xml";
import css from "highlight.js/lib/languages/css";
import json from "highlight.js/lib/languages/json";
import java from "highlight.js/lib/languages/java";
import typescript from "highlight.js/lib/languages/typescript";
import go from "highlight.js/lib/languages/go";
import c from "highlight.js/lib/languages/c";
import cpp from "highlight.js/lib/languages/cpp";
import csharp from "highlight.js/lib/languages/csharp";
import php from "highlight.js/lib/languages/php";
import "highlight.js/styles/github.css";

// 生成唯一ID的函数
const generateUniqueId = () => {
  // 时间戳 + 随机数组合，确保唯一性
  const timestamp = Date.now().toString(36);
  const randomNum = Math.floor(Math.random() * 10000).toString(36);
  return `code-block-${timestamp}-${randomNum}`;
};

// 为当前代码块生成唯一ID
const codeBlockId = ref(generateUniqueId());
const { copy } = useClipboard();
// 注册语言
hljs.registerLanguage("javascript", javascript);
hljs.registerLanguage("python", python);
hljs.registerLanguage("bash", bash);
hljs.registerLanguage("html", html);
hljs.registerLanguage("css", css);
hljs.registerLanguage("json", json);
hljs.registerLanguage("java", java);
hljs.registerLanguage("typescript", typescript);
hljs.registerLanguage("go", go);
hljs.registerLanguage("c", c);
hljs.registerLanguage("cpp", cpp);
hljs.registerLanguage("csharp", csharp);
hljs.registerLanguage("php", php);

const props = withDefaults(
  defineProps<{ code: string; language?: string; isLoading?: boolean }>(),
  {
    language: "text",
    isLoading: false,
  }
);
const generalDataStore = useGeneralDataStore();
const settingStore = useSettingStore();
const copied = ref(false);
const highlightedCode = ref("");
const isCodeReady = ref(false);

const codeToolbarRef = ref<HTMLElement | null>(null);
const codeContainerRef = ref<HTMLElement | null>(null);

const toolbarStyle = ref<Record<string, string>>({});
let onScrollHandler: (() => void) | null = null;
// 语言和扩展名映射
const langExtMap: Record<string, string> = {
  javascript: "js",
  typescript: "ts",
  vue: "vue",
  html: "html",
  css: "css",
  json: "json",
  java: "java",
  python: "py",
  c: "c",
  cpp: "cpp",
  "c#": "c#",
  go: "go",
  php: "php",
  sh: "sh",
  text: "text",
  txt: "txt",
};
// 高亮代码
const highlightCode = () => {
  try {
    // 保留原始换行符
    const codeToHighlight = props.code.replace(/\n$/, ""); // 移除末尾换行
    if (props.language && hljs.getLanguage(props.language)) {
      highlightedCode.value = hljs.highlight(codeToHighlight, {
        language: props.language,
      }).value;
    } else {
      highlightedCode.value = hljs.highlightAuto(codeToHighlight).value;
    }
    isCodeReady.value = true;
  } catch (e) {
    console.error("代码高亮错误:", e);
    highlightedCode.value = props.code
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;");
    isCodeReady.value = true;
  }
};
// 复制功能
const copyCode = async () => {
  try {
    await copy(props.code);
    copied.value = true;
    setTimeout(() => (copied.value = false), 2000);
  } catch (err) {
    console.error("复制失败:", err);
  }
};
// 下载功能
const copyDownload = useThrottleFn(() => {
  const ext = langExtMap[props.language || "text"] || "txt";
  const filename = `deepseek_${ext}_${Date.now()}.${ext}`;

  const blob = new Blob([props.code], { type: "text/plain;charset=utf-8" });
  const url = URL.createObjectURL(blob);

  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  a.click();

  URL.revokeObjectURL(url);
}, 2000);
// 代码运行/编辑查看代码编辑器
const copyRunOrOpenCodeEditor = useThrottleFn(async () => {
  if (!codeBlockId.value || !props.code) {
    console.error("错误：代码块 ID 或代码文本为空，无法切换！");
    return;
  }
  settingStore.setSmallCollapse(true);
  settingStore.setPhoneCollapse(true);

  if (generalDataStore.showCodeEditor) {
    generalDataStore.openRunOrEditCode(
      props.code,
      props.language || "text",
      codeBlockId.value
    );
  } else {
    generalDataStore.openRunOrEditCode(
      props.code,
      props.language || "text",
      codeBlockId.value
    );
  }
}, 2000);

// 初始化高亮
highlightCode();
watch(() => [props.code, props.language], highlightCode);

const funcBtnConfig = computed(() => {
  return [
    {
      isShow: true,
      clickFunc: copyCode,
      iconConfig: {
        name: copied.value ? "success" : "copy",
        height: "16px",
        width: "16px",
      },
      btnConfig: {
        backgroundColor: "#f5f5f5",
        hoverColor: "rgb(0 0 0 / 4%)",
        btnText: copied.value ? "已复制" : "复制",
      },
    },
    {
      isShow: true,
      clickFunc: copyDownload,
      iconConfig: {
        name: "download",
        height: "16px",
        width: "16px",
      },
      btnConfig: {
        backgroundColor: "#f5f5f5",
        hoverColor: "rgb(0 0 0 / 4%)",
        btnText: "下载",
      },
    },
    {
      isShow: props.language === "html" ? true : false,
      clickFunc: copyRunOrOpenCodeEditor,
      iconConfig: {
        name: "run",
        height: "16px",
        width: "16px",
      },
      btnConfig: {
        backgroundColor: "#f5f5f5",
        hoverColor: "rgb(0 0 0 / 4%)",
        btnText: "运行",
      },
    },
    {
      isShow: props.language === "html" ? false : true,
      clickFunc: copyRunOrOpenCodeEditor,
      iconConfig: {
        name: "openCodeEditor",
        height: "15px",
        width: "15px",
      },
      btnConfig: {
        backgroundColor: "#f5f5f5",
        hoverColor: "rgb(0 0 0 / 4%)",
        btnText: "编辑",
      },
    },
  ];
});

onMounted(() => {
  const scrollEl = document.querySelector(".session_bottom");
  if (!scrollEl || !codeContainerRef.value) return;

  // 状态锁：避免同一状态重复赋值
  let lastIsSticky = false;

  onScrollHandler = () => {
    if (!codeContainerRef.value || !codeToolbarRef.value) return;

    const containerRect = codeContainerRef.value.getBoundingClientRect();
    const toolbarHeight = codeToolbarRef.value.offsetHeight;

    // 优化判断逻辑：明确“进入代码块”的稳定条件
    // 条件1：代码块顶部进入 header 底部以下
    const isTopInView = containerRect.top < toolbarHeight;
    // 条件2：代码块底部未离开 header底部+工具栏高度以上
    const isBottomInView = containerRect.bottom > toolbarHeight;
    // 最终：同时满足则视为“在代码块内”
    const currentIsSticky = isTopInView && isBottomInView;

    // 状态锁：只有状态变化时才更新，避免频繁赋值抖动
    if (currentIsSticky !== lastIsSticky) {
      generalDataStore.isSticky = currentIsSticky;
      lastIsSticky = currentIsSticky;

      if (currentIsSticky) {
        toolbarStyle.value = {
          position: "sticky",
          top: "0px",
          zIndex: "999",
          boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
        };
      } else {
        toolbarStyle.value = {};
      }
    }
  };

  scrollEl.addEventListener("scroll", onScrollHandler, { passive: true });
});

onBeforeUnmount(() => {
  const scrollEl = document.querySelector(".session_bottom");
  if (onScrollHandler && scrollEl) {
    scrollEl.removeEventListener("scroll", onScrollHandler);
  }
});
</script>

<template>
  <div
    class="code-container"
    :class="`language-${language}`"
    ref="codeContainerRef"
    :id="codeBlockId"
  >
    <div class="code-toolbar" ref="codeToolbarRef" :style="toolbarStyle">
      <span class="language-label">{{ language || "text" }}</span>
      <div class="code-func-div">
        <template v-if="isCodeReady">
          <CusTipBtn
            v-for="(item, index) in funcBtnConfig"
            v-show="item.isShow"
            :key="index"
            :isTooltip="false"
            :clickFun="item.clickFunc"
            :iconConfig="item.iconConfig"
            :btnConfig="item.btnConfig"
          />
        </template>
      </div>
    </div>
    <pre v-if="isCodeReady">
        <code class="hljs" v-html="highlightedCode"></code>
      </pre>
    <pre v-else class="loading-placeholder">
        <code>
          <div class="loading-line"></div>
          <div class="loading-line" style="width: 80%"></div>
          <div class="loading-line" style="width: 60%"></div>
        </code>
      </pre>
  </div>
</template>

<style scoped lang="scss">
.code-container {
  border-radius: 12px;
  background: #fafafa;
  margin: 10px 0;
  .code-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 12px;
    background: #f5f5f5;
    border-radius: 12px 12px 0 0;
    color: #aaa;
    font-size: 0.85em;
    transition: box-shadow 0.2s ease;
    font-family: Inter, "Helvetica Neue", Helvetica, "PingFang SC",
      "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
    .language-label {
      font-size: 13px;
      color: #525252;
    }
  }
  pre {
    display: flex;
    margin: 0;
    padding: calc(1.143 * 8px) calc(1.143 * 12px);
    overflow-x: auto;
    code {
      display: block;
      font-family: Inter, "Helvetica Neue", Helvetica, "PingFang SC",
        "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
      line-height: 1.5;
      color: #494949;
      font-size: 1em;
      white-space: pre-wrap;
      word-break: break-all;
      background: none;
    }
  }
  .loading-placeholder {
    padding: 1em;
    margin: 0;
    background: #f5f5f5;
    border-radius: 0 0 4px 4px;
    .loading-line {
      height: 1em;
      background: #e0e0e0;
      margin-bottom: 0.5em;
      border-radius: 2px;
      animation: pulse 1.5s infinite ease-in-out;
    }
  }
}
@keyframes pulse {
  0%,
  100% {
    opacity: 0.6;
  }
  50% {
    opacity: 1;
  }
}
</style>
